Capturing Screenshots
QuickPose composites the camera feed and skeleton overlay into a single hardware surface, which means standard screenshot tools cannot read the pixels back. The SDK provides a native captureFrame method on each platform to capture the composited camera + overlay image.
- Swift
- Kotlin XML
- Kotlin Compose
- React Native
On iOS the composited frame is available as overlayState.image (UIImage) in your onFrame callback. You can save or share this directly:
quickPose.start(features: [.overlay(.wholeBody)], onFrame: { status, image, features, feedback, landmarks in
if case .success(_, _) = status {
overlayImage = image
// image is a UIImage of camera + overlay, ready to save or share
}
})
To share via the system share sheet:
func shareScreenshot() {
guard let image = overlayImage else { return }
let activityVC = UIActivityViewController(activityItems: [image], applicationActivities: nil)
UIApplication.shared.windows.first?.rootViewController?.present(activityVC, animated: true)
}
On Android, QuickPoseCameraSwitchView provides a captureFrame method (core 0.21+) that captures the composited camera + overlay as a Bitmap:
cameraSwitchView?.captureFrame { bitmap ->
if (bitmap != null) {
// bitmap contains camera + overlay, ready to save or share
println("Captured frame: ${bitmap.width}x${bitmap.height}")
}
}
To share via the system share sheet:
cameraSwitchView?.captureFrame { bitmap ->
bitmap?.let {
val uri = saveBitmapToCache(it) // save to app cache
val intent = Intent(Intent.ACTION_SEND).apply {
type = "image/png"
putExtra(Intent.EXTRA_STREAM, uri)
}
startActivity(Intent.createChooser(intent, "Share Screenshot"))
}
}
You can also use the lower-level static method on QuickPose (core 0.20+) if you need to capture the camera and overlay separately:
QuickPose.captureFrame(cameraSwitchView!!, overlayView) { bitmap ->
// bitmap contains camera + overlay
}
In Compose, store a reference to QuickPoseCameraSwitchView and call captureFrame (core 0.21+):
var cameraSwitchView by remember { mutableStateOf<QuickPoseCameraSwitchView?>(null) }
AndroidView(
factory = { context ->
val view = QuickPoseCameraSwitchView(context, quickPose)
cameraSwitchView = view
coroutineScope.launch { view.start(useFrontCamera) }
view
}
)
Button(onClick = {
cameraSwitchView?.captureFrame { bitmap ->
// bitmap contains camera + overlay, ready to save or share
}
}) {
Text("Capture Screenshot")
}
From @quickpose/react-native 0.3.2+, the QuickPoseView ref exposes two imperative methods:
import React, { useRef } from 'react';
import { TouchableOpacity, Text } from 'react-native';
import { QuickPoseView, QuickPoseViewRef } from '@quickpose/react-native';
export default function App() {
const poseRef = useRef<QuickPoseViewRef>(null);
return (
<>
<QuickPoseView
ref={poseRef}
sdkKey="YOUR SDK KEY HERE"
features={['fitness.squats']}
style={{ flex: 1 }}
/>
<TouchableOpacity onPress={() => poseRef.current?.shareFrame('My squats')}>
<Text>Share Screenshot</Text>
</TouchableOpacity>
</>
);
}
shareFrame(title?): Promise<void>
Captures the current camera + overlay frame and opens the native share sheet (iOS UIActivityViewController, Android ACTION_SEND chooser). Resolves when the sheet is presented.
captureFrame(): Promise<string>
Captures the current frame as a PNG and returns a platform-local URI (file:// on iOS, content:// on Android):
const uri = await poseRef.current!.captureFrame();
const bytes = await (await fetch(uri)).arrayBuffer();
No extra setup is needed — the plugin registers its own FileProvider on Android so the generated URI can cross app boundaries for sharing.